home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / ODF / Found / FWNotifn / FWIntSpc.cpp < prev    next >
Encoding:
Text File  |  1996-09-17  |  21.8 KB  |  652 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                FWIntSpc.cpp
  4. //    Release Version:    $ ODF 2 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #ifndef FWINTSPC_H
  11. #include "FWIntSpc.h"
  12. #endif
  13.  
  14. #ifndef FWNOTIFR_H
  15. #include "FWNotifr.h"
  16. #endif
  17.  
  18. #ifndef FWNOTIFN_H
  19. #include "FWNotifn.h"
  20. #endif
  21.  
  22. //========================================================================================
  23. //    Template Instantiations
  24. //========================================================================================
  25.  
  26. FW_DEFINE_AUTO_TEMPLATE(FW_TOrderedCollection, FW_PrivInterestTag)
  27. FW_DEFINE_AUTO_TEMPLATE(FW_TOrderedCollection, FW_SPrivTaggableInterest)
  28. FW_DEFINE_AUTO_TEMPLATE(FW_TOrderedCollectionIterator, FW_SPrivTaggableInterest)
  29.  
  30. #ifdef FW_USE_TEMPLATE_PRAGMAS
  31.  
  32. #pragma template_access public
  33.  
  34. #pragma template FW_TOrderedCollection<FW_SPrivTaggableInterest>
  35. #pragma template FW_TOrderedCollectionIterator<FW_SPrivTaggableInterest>
  36. #pragma template FW_TMap<FW_ObjectID, FW_SPrivNotifierEntry>
  37. #pragma template FW_TPair<FW_ObjectID, FW_SPrivNotifierEntry>
  38. #pragma template FW_TMap<FW_ObjectID, FW_SPrivReceiverEntry>
  39. #pragma template FW_TPair<FW_ObjectID, FW_SPrivReceiverEntry>
  40. #pragma template FW_TPrivDestroyer<FW_CPrivInterestSpace>
  41.  
  42. #else
  43.  
  44. template class FW_TOrderedCollection<FW_SPrivTaggableInterest>;
  45. template class FW_TOrderedCollectionIterator<FW_SPrivTaggableInterest>;
  46. template class FW_TMap<FW_ObjectID, FW_SPrivNotifierEntry>;
  47. template class FW_TPair<FW_ObjectID, FW_SPrivNotifierEntry>;
  48. template class FW_TMap<FW_ObjectID, FW_SPrivReceiverEntry>;
  49. template class FW_TPair<FW_ObjectID, FW_SPrivReceiverEntry>;
  50. template class FW_TPrivDestroyer<FW_CPrivInterestSpace>;
  51.  
  52. #endif
  53.  
  54. //========================================================================================
  55. //    Static Allocations
  56. //========================================================================================
  57.  
  58. FW_CPrivInterestSpace* FW_CPrivInterestSpace::fgInstance;
  59. FW_TPrivDestroyer<FW_CPrivInterestSpace> FW_CPrivInterestSpace::fgDestroyer;
  60.  
  61. //========================================================================================
  62. //    Static Comparison Callbacks
  63. //========================================================================================
  64.  
  65. //----------------------------------------------------------------------------------------
  66. //    FW_CompareNotifierEntries
  67. //----------------------------------------------------------------------------------------
  68.  
  69. static int FW_CompareNotifierEntries(void* first, void* second)
  70. {
  71.     return (((FW_CPrivNotifierInterestPair*)first)->fKey - ((FW_CPrivNotifierInterestPair*)second)->fKey);
  72. }
  73.  
  74. //----------------------------------------------------------------------------------------
  75. //    FW_NotifierEntryMatchProc
  76. //----------------------------------------------------------------------------------------
  77.  
  78. static FW_Boolean FW_NotifierEntryMatchProc(const void* v1, const void* v2)
  79. {
  80.     const FW_SPrivTaggableInterest* value1 = (FW_SPrivTaggableInterest*)v1;
  81.     const FW_SPrivTaggableInterest* value2 = (FW_SPrivTaggableInterest*)v2;
  82.     
  83.         // compare receiver and message...don't compare fMarked
  84.     return ((value1->fReceiver == value2->fReceiver) && (value1->fMessage == value2->fMessage));
  85. }
  86.  
  87. //----------------------------------------------------------------------------------------
  88. //    FW_ReceiverEntryMatchProc
  89. //----------------------------------------------------------------------------------------
  90.  
  91. static FW_Boolean FW_ReceiverEntryMatchProc(const void* v1, const void* v2)
  92. {
  93.     return ((*(FW_CInterest*)v1) == (*(FW_CInterest*)v2));
  94. }
  95.  
  96. //----------------------------------------------------------------------------------------
  97. //    FW_CompareReceiverEntries
  98. //----------------------------------------------------------------------------------------
  99.  
  100. static int FW_CompareReceiverEntries(void* first, void* second)
  101. {
  102.     FW_ObjectID firstID = ((FW_CPrivReceiverInterestPair*)first)->fKey;
  103.     FW_ObjectID secondID =  ((FW_CPrivReceiverInterestPair*)second)->fKey;
  104.     
  105.     return (((FW_CPrivReceiverInterestPair*)first)->fKey - ((FW_CPrivReceiverInterestPair*)second)->fKey);
  106. }
  107.  
  108. //========================================================================================
  109. //    class FW_CPrivInterestSpace
  110. //========================================================================================
  111.  
  112. //----------------------------------------------------------------------------------------
  113. //    FW_CPrivInterestSpace::FW_CPrivInterestSpace
  114. //----------------------------------------------------------------------------------------
  115.  
  116. FW_CPrivInterestSpace::FW_CPrivInterestSpace() :
  117.     fLastNotifierID(0),
  118.     fLastReceiverID(0),
  119.     fLastTag(0),
  120.     fNotifierInterestMap(FW_CompareNotifierEntries),
  121.     fReceiverInterestMap(FW_CompareReceiverEntries)
  122. {
  123. }
  124.  
  125. //----------------------------------------------------------------------------------------
  126. //    FW_CPrivInterestSpace::~FW_CPrivInterestSpace
  127. //----------------------------------------------------------------------------------------
  128.  
  129. FW_CPrivInterestSpace::~FW_CPrivInterestSpace()
  130. {
  131.     fgInstance = NULL;
  132. }
  133.  
  134. //----------------------------------------------------------------------------------------
  135. //    FW_CPrivInterestSpace::Instance
  136. //----------------------------------------------------------------------------------------
  137.  
  138. FW_CPrivInterestSpace* FW_CPrivInterestSpace::Instance()
  139. {
  140.     if (!fgInstance)
  141.     {
  142.         fgInstance = new FW_CPrivInterestSpace;
  143.         fgDestroyer.SetDoomed(fgInstance);
  144.     }
  145.     return fgInstance;
  146. }
  147.  
  148. //----------------------------------------------------------------------------------------
  149. //    FW_CPrivInterestSpace::AddNotifierInterest
  150. //----------------------------------------------------------------------------------------
  151.  
  152. void FW_CPrivInterestSpace::AddNotifierInterest(FW_MReceiver* receiver, 
  153.                                             const FW_CInterest& interest)
  154. {
  155.     FW_ASSERT(receiver->IsConnected());
  156.  
  157.     FW_MNotifier* notifier = interest.GetNotifier();
  158.     FW_ObjectID notifierID = notifier->PrivGetNotifierID();
  159.     FW_CPrivNotifierInterestPair* pair;
  160.  
  161.     if (notifierID == 0)
  162.     {
  163.         FW_SPrivNotifierEntry entry;
  164.         
  165.         notifierID = GetNextNotifierID();
  166.         notifier->PrivSetNotifierID(notifierID);
  167.         
  168.         entry.fNotifier = notifier;
  169.         entry.fTaggedInterestList = FW_NEW(FW_CPrivTaggableInterestList, (FW_NotifierEntryMatchProc));
  170.  
  171.         pair = fNotifierInterestMap.Add(notifierID, entry);
  172.     }
  173.     else
  174.         pair = fNotifierInterestMap.Find(notifierID);
  175.  
  176.     FW_ASSERT(pair);
  177.     
  178.     FW_CPrivTaggableInterestList* interestList = pair->fValue.fTaggedInterestList;
  179.     
  180.     FW_SPrivTaggableInterest* entry = new FW_SPrivTaggableInterest;
  181.     entry->fReceiver = receiver;
  182.     entry->fMessage = interest.GetMessage();
  183.     entry->fTags[0] = entry->fTags[1] = 0;
  184.     entry->fTagCollection = NULL;
  185.     
  186.     if (interestList->Contains(entry))
  187.     {
  188.         FW_DEBUG_MESSAGE("FW_CPrivInterestSpace::AddNotifierInterest - Trying to add an interest that already exists");
  189.         delete entry;
  190.         return;
  191.     }
  192.  
  193.     interestList->AddLast(entry);
  194. }
  195.  
  196. //----------------------------------------------------------------------------------------
  197. //    FW_CPrivInterestSpace::AddReceiverInterest
  198. //----------------------------------------------------------------------------------------
  199.  
  200. void FW_CPrivInterestSpace::AddReceiverInterest(FW_MReceiver* receiver, 
  201.                                             const FW_CInterest& interest)
  202. {    
  203.     FW_ObjectID receiverID = receiver->PrivGetReceiverID();
  204.     FW_CPrivReceiverInterestPair* receiverPair;
  205.     
  206.     if (receiverID == 0)
  207.     {
  208.         FW_SPrivReceiverEntry entry;
  209.         
  210.         receiverID = GetNextReceiverID();
  211.         receiver->PrivSetReceiverID(receiverID);
  212.         
  213.         entry.fReceiver = receiver;
  214.         entry.fInterestList = FW_NEW(FW_CInterestCollection, (FW_ReceiverEntryMatchProc));
  215.         
  216.         receiverPair = fReceiverInterestMap.Add(receiverID, entry);
  217.     }
  218.     else
  219.         receiverPair = fReceiverInterestMap.Find(receiverID);
  220.     
  221.     FW_ASSERT(receiverPair);
  222.  
  223.     FW_CInterestCollection* interestList = receiverPair->fValue.fInterestList;
  224.     
  225.     if (interestList->Contains(&interest))
  226.     {
  227.         FW_DEBUG_MESSAGE("FW_CPrivInterestSpace::AddReceiverInterest - Trying to add an interest that already exists");
  228.         return;
  229.     }
  230.     
  231.     FW_CInterest* interestCopy = new FW_CInterest(interest);
  232.     interestList->AddLast(interestCopy);
  233.     
  234.     if (receiver->IsConnected())
  235.         AddNotifierInterest(receiver, interest);
  236. }
  237.  
  238. //----------------------------------------------------------------------------------------
  239. //    FW_CPrivInterestSpace::RemoveNotifierInterest
  240. //----------------------------------------------------------------------------------------
  241.  
  242. void FW_CPrivInterestSpace::RemoveNotifierInterest(FW_MReceiver* receiver, const FW_CInterest& interest)
  243. {
  244.     FW_MNotifier* notifier = interest.GetNotifier();
  245.     FW_ObjectID notifierID = notifier->PrivGetNotifierID();
  246.     
  247.     FW_ASSERT(notifierID != 0);    // if this is false, the interest can't be registered
  248.         
  249.     FW_CPrivNotifierInterestPair* pair = fNotifierInterestMap.Find(notifierID);
  250.     if (pair && (pair->fValue.fNotifier == notifier))
  251.     {
  252.         FW_Message message = interest.GetMessage();
  253.         FW_CPrivTaggableInterestList* interestList = pair->fValue.fTaggedInterestList;
  254.         FW_SPrivTaggableInterest* currentInterest = NULL;
  255.         FW_SPrivTaggableInterest* sentinel = NULL;
  256.         FW_Boolean done = false;
  257.         
  258.         // there should only be one instance of the specified interest, but we
  259.         // take a conservative approach and walk the entire interest list
  260.         while (!done)
  261.         {
  262.             currentInterest = sentinel ? interestList->After(sentinel) : interestList->First();
  263.                 
  264.             if (currentInterest == NULL)
  265.                 done = true;
  266.             else
  267.             {
  268.                 if ((currentInterest->fReceiver == receiver) && (currentInterest->fMessage == message))
  269.                 {
  270.                     interestList->Remove(currentInterest);
  271.                     delete currentInterest->fTagCollection;
  272.                     delete(currentInterest);
  273.                 }
  274.                 else
  275.                     sentinel = currentInterest;
  276.             }
  277.         } 
  278.         
  279.         if (interestList->Count() == 0)
  280.         {
  281.             delete interestList;
  282.             fNotifierInterestMap.Remove(notifierID);
  283.             notifier->PrivSetNotifierID(0);
  284.         }
  285.     }
  286. }
  287.  
  288. //----------------------------------------------------------------------------------------
  289. //    FW_CPrivInterestSpace::RemoveReceiverInterest
  290. //----------------------------------------------------------------------------------------
  291.  
  292. void FW_CPrivInterestSpace::RemoveReceiverInterest(FW_MReceiver* receiver, 
  293.                                             const FW_CInterest& interest,
  294.                                             FW_Boolean removeNotifierInterest)
  295. {
  296.     FW_ObjectID receiverID = receiver->PrivGetReceiverID();
  297.     FW_ASSERT(receiverID != 0);
  298.     FW_CPrivReceiverInterestPair* pair = fReceiverInterestMap.Find(receiverID);
  299.     
  300.     if (pair && (pair->fValue.fReceiver == receiver))
  301.     {
  302.         FW_CInterest* entryToDelete = NULL;
  303.         FW_CInterestCollection* interestList = pair->fValue.fInterestList;
  304.         FW_CInterestCollectionIterator iter(interestList);
  305.         
  306.         for (FW_CInterest* curEntry = iter.First(); iter.IsNotComplete(); curEntry = iter.Next())
  307.         {
  308.             if (*curEntry == interest)
  309.             {
  310.                 entryToDelete = curEntry;
  311.                 break;
  312.             }
  313.         }
  314.         
  315.         if (entryToDelete)
  316.         {
  317.             interestList->Remove(entryToDelete);
  318.             delete entryToDelete;
  319.             
  320.             // only attempt to remove the notifier interest if the
  321.             // receiver interest was found and removed. this handles
  322.             // the case where a receiver cached a ptr to a notifier,
  323.             // then the notifier was deleted, then receiver tried
  324.             // to remove the interest using the cached ptr (which is
  325.             // now dangling)
  326.             if (removeNotifierInterest && receiver->IsConnected())
  327.                 RemoveNotifierInterest(receiver, interest);
  328.         }
  329.     }
  330. }
  331.  
  332. //----------------------------------------------------------------------------------------
  333. //    FW_CPrivInterestSpace::HasInterest
  334. //----------------------------------------------------------------------------------------
  335.  
  336. FW_Boolean FW_CPrivInterestSpace::HasInterest(const FW_MReceiver* receiver,
  337.                                         const FW_CInterest& interest)
  338. {
  339.     FW_Boolean result = false;
  340.     FW_MNotifier* notifier = interest.GetNotifier();
  341.     FW_ObjectID notifierID = notifier->PrivGetNotifierID();
  342.     FW_Message message = interest.GetMessage();
  343.     
  344.     if (notifierID != 0)
  345.     {
  346.         FW_CPrivNotifierInterestPair* pair = fNotifierInterestMap.Find(notifierID);
  347.         if (pair)
  348.         {
  349.             FW_TOrderedCollectionIterator<FW_SPrivTaggableInterest> iter(pair->fValue.fTaggedInterestList);
  350.             for (FW_SPrivTaggableInterest* curEntry = iter.First(); 
  351.                         !result && iter.IsNotComplete(); 
  352.                         curEntry = iter.Next())
  353.             {
  354.                 if ((curEntry->fReceiver == receiver) && (curEntry->fMessage == message))
  355.                     result = true;
  356.             }
  357.         }
  358.     }
  359.     return result;
  360. }
  361.  
  362. //----------------------------------------------------------------------------------------
  363. //    FW_CPrivInterestSpace::Notify
  364. //----------------------------------------------------------------------------------------
  365.  
  366. void FW_CPrivInterestSpace::Notify(Environment* ev,
  367.                             const FW_CNotification& notification)
  368. {
  369.     FW_MNotifier* notifier = notification.GetNotifier();
  370.     FW_ObjectID notifierID = notifier->PrivGetNotifierID();
  371.     
  372.     if (notifierID == 0)    // notifier has no interests
  373.         return;
  374.     
  375.     FW_Message message = notification.GetMessage();
  376.     
  377.     // only interests that are installed when notification begins get notified.
  378.     // if additional interests are installed during notification, they will
  379.     // not get notified. this is implemented by first iterating through
  380.     // installed notifications, and marking them. we then conservatively
  381.     // iterate through marked interests, until they are all satisfied.
  382.     // this implementation allows interests to be deleted during notification.
  383.     
  384.     // the common case is for a notifier to have a single receiver interested
  385.     // in a specific notification. when this case is detected, the receiver
  386.     // is notified immediately, and the multiple iteration algorithm is not
  387.     // used.
  388.     FW_CPrivNotifierInterestPair* pair = fNotifierInterestMap.Find(notifierID);
  389.     FW_ASSERT(pair);
  390.     FW_ASSERT(notifier == pair->fValue.fNotifier);
  391.     
  392.     unsigned short                 interestsTagged;
  393.     FW_SPrivTaggableInterest*     interestEntry;
  394.     FW_PrivInterestTag                tag = GetNextTag();
  395.         
  396.     interestEntry = TagInterests(pair->fValue.fTaggedInterestList, message, tag, interestsTagged);
  397.         
  398.     // receivers needing notification are now marked. there are three possible states
  399.     // at this point
  400.     //    a). no appropriate interests existed. this case is detected when foundMultiple
  401.     //        is false and interestEntry is NULL
  402.     //    b).    a single eligible interest existed. this case is detected when foundMultiple
  403.     //        is false, and interestEntry is not NULL
  404.     //    c).    multiple eligible receivers were found. this case is detected when foundMultiple
  405.     //        is true
  406.             
  407.     if (interestsTagged == 1)
  408.     {
  409.         if (interestEntry)
  410.         {
  411.             // clear flag before notifying, in case entry is deleted as a result of notification
  412.             FW_Boolean removed = RemoveTagFromInterest(interestEntry, tag);
  413.             FW_ASSERT(removed);
  414.             SendNotificationToReceiver(ev, interestEntry->fReceiver, notification);
  415.         }
  416.     }
  417.     else
  418.     {
  419.         do
  420.         {
  421.             interestEntry = NULL;
  422.             pair = fNotifierInterestMap.Find(notifierID);
  423.             // validate that the notifier associated with the pair is, in fact, the
  424.             // same notifier that initiated the notification. this virtually guaranteed
  425.             // to be true because of the use of notifier IDs. the use of notifier id's
  426.             // as keys is specifically to protect against the case where, as a consequence
  427.             // of a notification, a notifier is deleted and, at the same time, a new
  428.             // notifier is created at the same address. using object ids _and_ object
  429.             // pointers prevents us from mistaking the new object's list for the old one.
  430.             if (pair && (pair->fValue.fNotifier == notifier))
  431.             {
  432.                 FW_TOrderedCollectionIterator<FW_SPrivTaggableInterest> iter(pair->fValue.fTaggedInterestList);
  433.                 for (FW_SPrivTaggableInterest* curEntry = iter.First(); iter.IsNotComplete(); curEntry = iter.Next())
  434.                 {
  435.                     if (RemoveTagFromInterest(curEntry, tag))
  436.                     {
  437.                         FW_ASSERT(curEntry->fMessage == message);
  438.                         interestEntry = curEntry;
  439.                         break;
  440.                     }
  441.                 } 
  442.             }
  443.             
  444.             if (interestEntry)
  445.                 SendNotificationToReceiver(ev, interestEntry->fReceiver, notification);
  446.             
  447.         } while (interestEntry);
  448.     }
  449. }
  450.  
  451. //----------------------------------------------------------------------------------------
  452. //    FW_CPrivInterestSpace::AddTagToInterest
  453. //----------------------------------------------------------------------------------------
  454.  
  455. void FW_CPrivInterestSpace::AddTagToInterest(FW_SPrivTaggableInterest* interest,
  456.                                             FW_PrivInterestTag tag)
  457. {
  458.     if (interest->fTags[0] == 0)
  459.         interest->fTags[0] = tag;
  460.     else if (interest->fTags[1] == 0)
  461.         interest->fTags[1] = tag;
  462.     else
  463.     {
  464.         if (!interest->fTagCollection)
  465.             interest->fTagCollection = FW_NEW(FW_CPrivInterestTagCollection, ());
  466.         interest->fTagCollection->AddLast((FW_PrivInterestTag*)tag);
  467.             
  468.     }
  469. }
  470.  
  471. //----------------------------------------------------------------------------------------
  472. //    FW_CPrivInterestSpace::RemoveTagFromInterest
  473. //----------------------------------------------------------------------------------------
  474.  
  475. FW_Boolean FW_CPrivInterestSpace::RemoveTagFromInterest(FW_SPrivTaggableInterest* interest,
  476.                                                         FW_PrivInterestTag tag)
  477. {
  478.     FW_Boolean interestWasTagged = false;
  479.     FW_PrivInterestTag* openSlot = NULL;
  480.     
  481.     if (interest->fTags[0] == tag)
  482.         openSlot = &interest->fTags[0];
  483.     else if (interest->fTags[1] == tag)
  484.         openSlot = &interest->fTags[1];
  485.         
  486.     if (openSlot)
  487.     {
  488.         *openSlot = 0;
  489.         interestWasTagged = true;
  490.     }
  491.         
  492.     if (interest->fTagCollection)
  493.     {    
  494.         FW_Boolean collectionShrunk = false;
  495.         if (openSlot)
  496.         {
  497.             *openSlot = (FW_PrivInterestTag)interest->fTagCollection->RemoveLast();
  498.             collectionShrunk = true;
  499.         }
  500.         else if (interest->fTagCollection->Contains((FW_PrivInterestTag*)tag))
  501.         {
  502.             interest->fTagCollection->Remove((FW_PrivInterestTag*)tag);
  503.             interestWasTagged = true;
  504.             collectionShrunk = true;
  505.         }
  506.         
  507.         if (collectionShrunk && (interest->fTagCollection->Count() == 0))
  508.         {
  509.             delete interest->fTagCollection;
  510.             interest->fTagCollection = NULL;
  511.         }
  512.     }
  513.     
  514.     return interestWasTagged;
  515. }
  516.  
  517. //----------------------------------------------------------------------------------------
  518. //    FW_CPrivInterestSpace::TagInterests
  519. //----------------------------------------------------------------------------------------
  520.  
  521. FW_SPrivTaggableInterest* FW_CPrivInterestSpace::TagInterests(FW_CPrivTaggableInterestList* interestList,
  522.                                                     FW_Message message,
  523.                                                     FW_PrivInterestTag tag,
  524.                                                     unsigned short& interestsTagged)
  525. {
  526.     FW_SPrivTaggableInterest* firstTaggedInterest = NULL;
  527.     interestsTagged = 0;
  528.     
  529.     FW_TOrderedCollectionIterator<FW_SPrivTaggableInterest> iter(interestList);
  530.     for (FW_SPrivTaggableInterest* curEntry = iter.First(); iter.IsNotComplete(); curEntry = iter.Next())
  531.     {
  532.         if (curEntry->fMessage == message)
  533.         {
  534.             ++interestsTagged;
  535.             if (!firstTaggedInterest)
  536.                 firstTaggedInterest = curEntry;
  537.  
  538.             AddTagToInterest(curEntry, tag);
  539.         }
  540.     }
  541.     
  542.     return firstTaggedInterest;
  543. }
  544.  
  545. //----------------------------------------------------------------------------------------
  546. //    FW_CPrivInterestSpace::SendNotificationToReceiver
  547. //----------------------------------------------------------------------------------------
  548.  
  549. void FW_CPrivInterestSpace::SendNotificationToReceiver(Environment* ev,
  550.                                                 FW_MReceiver* receiver,
  551.                                                 const FW_CNotification& notification)
  552. {
  553.     FW_TRY
  554.     {
  555.         receiver->HandleNotification(ev, notification);
  556.     }
  557.     FW_CATCH_BEGIN
  558.     FW_CATCH_EVERYTHING()
  559.     {
  560.         // swallow exceptions
  561.     }
  562.     FW_CATCH_END
  563. }
  564.  
  565. //----------------------------------------------------------------------------------------
  566. //    FW_CPrivInterestSpace::RemoveReceiver
  567. //----------------------------------------------------------------------------------------
  568.  
  569. void FW_CPrivInterestSpace::RemoveReceiver(FW_MReceiver* receiver)
  570. {
  571.     FW_ObjectID receiverID = receiver->PrivGetReceiverID();
  572.     if (receiverID == 0)
  573.         return;
  574.         
  575.     FW_CPrivReceiverInterestPair* pair = fReceiverInterestMap.Find(receiverID);
  576.     FW_ASSERT(pair);
  577.     FW_ASSERT(pair->fValue.fReceiver == receiver);
  578.     FW_Boolean receiverIsConnected = receiver->IsConnected();
  579.     FW_CInterestCollection* interestList = pair->fValue.fInterestList;
  580.     FW_CInterest* lastEntry;
  581.     do
  582.     {
  583.         lastEntry = interestList->RemoveLast();
  584.         if (lastEntry)
  585.         {
  586.             if (receiverIsConnected)
  587.                 RemoveNotifierInterest(receiver, *lastEntry);
  588.             delete lastEntry;
  589.         }
  590.     } while (lastEntry);
  591.     
  592.     delete interestList;
  593.     fReceiverInterestMap.Remove(receiverID);
  594.     receiver->PrivSetReceiverID(0);
  595. }
  596.  
  597. //----------------------------------------------------------------------------------------
  598. //    FW_CPrivInterestSpace::RemoveNotifier
  599. //----------------------------------------------------------------------------------------
  600.  
  601. void FW_CPrivInterestSpace::RemoveNotifier(FW_MNotifier* notifier)
  602. {
  603.     FW_ObjectID notifierID = notifier->PrivGetNotifierID();
  604.     if (notifierID == 0)
  605.         return;
  606.     
  607.     FW_CPrivNotifierInterestPair* pair = fNotifierInterestMap.Find(notifierID);
  608.     FW_ASSERT(pair);
  609.     FW_ASSERT(notifier == pair->fValue.fNotifier);
  610.     FW_ASSERT(pair->fValue.fTaggedInterestList);
  611.     
  612.     FW_CPrivTaggableInterestList* interestList = pair->fValue.fTaggedInterestList;
  613.     FW_SPrivTaggableInterest* lastEntry;
  614.     do
  615.     {
  616.         lastEntry = interestList->RemoveLast();
  617.         if (lastEntry)
  618.         {    
  619.             RemoveReceiverInterest(lastEntry->fReceiver, FW_CInterest(notifier, lastEntry->fMessage), false);
  620.             delete lastEntry->fTagCollection;
  621.             delete lastEntry;
  622.         }
  623.     } while (lastEntry);
  624.     
  625.     delete interestList;
  626.     fNotifierInterestMap.Remove(notifierID);
  627.     notifier->PrivSetNotifierID(0);
  628. }
  629.  
  630. //----------------------------------------------------------------------------------------
  631. //    FW_CPrivInterestSpace::SetReceiverIsConnected
  632. //----------------------------------------------------------------------------------------
  633.  
  634. void FW_CPrivInterestSpace::SetReceiverIsConnected(FW_MReceiver* receiver, FW_Boolean connected)
  635. {
  636.     FW_ObjectID receiverID = receiver->PrivGetReceiverID();
  637.     if (receiverID == 0)
  638.         return;
  639.         
  640.     FW_CPrivReceiverInterestPair* pair = fReceiverInterestMap.Find(receiverID);
  641.     FW_ASSERT(pair);
  642.     FW_ASSERT(pair->fValue.fReceiver == receiver);
  643.     
  644.     FW_TOrderedCollectionIterator<FW_CInterest> iter(pair->fValue.fInterestList);
  645.     for (FW_CInterest* interest = iter.First(); iter.IsNotComplete(); interest = iter.Next())
  646.     {
  647.         if (connected)
  648.             AddNotifierInterest(receiver, *interest);
  649.         else
  650.             RemoveNotifierInterest(receiver, *interest);
  651.     }
  652. }